<?php
/**
 * coreRouterMapAbstract
 *
 * 라우팅 맵 추상화 클래스
 *
 * @package router
 * @author  Platform Team
 */

abstract class coreRouterMapAbstract
{
    /**
     * 컨트롤러명
     * @var string
     */
    protected $sController = false;

    /**
     * 컨트롤러 패쓰 (contAdminLogin 이라면 Admin/Login 이라고 할당)
     * @var string
     */
    protected $sControllerPath = false;

    /**
     * 메소드명
     * @var string
     */
    protected $sMethod = false;

    /**
     * 메소드 파라미터
     * @var array
     */
    protected $aMethodParam = false;

    /**
     * 매핑 규칙 배열(Segment 방식일 경우 유효)
     * @var array
     */
    protected $aMap = false;

    /**
     * 에러메세지
     * @var string
     */
    protected $sErrorMsg = false;

    /**
     * CGI 환경에서의 PATH_INFO 문제 수정 여부
     * @var boolean
     */
    protected $isFixCgiPathinfo = false;

    /**
     * 매핑 파서 추상화 메소드
     */
    abstract public function parse();



    /**
     * 생성자
     * @param array $aMap             (매핑규칙 배열)
     * @param boolean $isFixCgiPathinfo (CGI 환경에서의 PATH_INFO 문제 수정 여부)
     */
    final public function __construct($aMap, $isFixCgiPathinfo)
    {
        $this->aMap = $aMap;
        $this->isFixCgiPathinfo = $isFixCgiPathinfo;
    }

    /**
     * 컨트롤러명 반환
     */
    final public function getController()
    {
        return $this->sController;
    }

    /**
     * 컨트롤러 패쓰 반환
     */
    final public function getControllerPath()
    {
        return $this->sControllerPath;
    }

    /**
     * 메소드명 반환
     */
    final public function getMethod()
    {
        return $this->sMethod;
    }

    /**
     * 메소드 파라미터 반환
     */
    final public function getMethodParam()
    {
        return $this->aMethodParam;
    }

    /**
     * 에러메세지 반환 (에러가 발생되지 않은 경우는 false 반환)
     */
    final public function getErrorMsg()
    {
        return ($this->sErrorMsg !== false) ? $this->sErrorMsg : false;
    }

    /**
     * 패쓰 정보를 받아서 컨트롤러 관련 정보를 반환한다.
     *
     * 두번째 인자에 음수값을 부여하면 해당 깊이 만큼 재귀호출을 시도함
     * (-1을 부여하고 /admin/login/exec 라는 패쓰정보로 해당되는 컨트롤러를 못찾았을 경우 /admin/login 으로 다시 시도함)
     * (-2를 부여했을 경우는 /admin 까지 들어가서 검색)
     *
     * @param string $sPath
     * @param int $iDepth
     * @param string $sMethod
     * @return array(
     *  'controller' => 컨트롤러명,
     *  'method' => 메소드명,
     *  'path' => 컨트롤러패쓰
     * ) | false
     */
    final protected function parsePath($sPath=null, $iDepth=0, $sMethod=FW_ROUTE_DEFAULT_METHOD)
    {
        if (empty($sPath)) {
            $sPath = FW_ROUTE_DEFAULT_CONTROLLER;
        }

        if (preg_match_all('/[a-z0-9]+/i', $sPath, $aMatch) === 0) {
            return false;
        }

        $sSuffix = '';
        $aPathmatch = array();

        foreach ($aMatch[0] as $match) {
            $sKey = ucfirst(strtolower($match));
            $sSuffix .= $sKey;
            $aPathmatch[] = $sKey;
        }

        $iCount = count($aPathmatch);
        $sController = FW_CLASS_PREFIX_CONT . $sSuffix;

        if (!class_exists($sController)) {
            if ($iCount <= 1) return false;

            if ($iDepth < 0) {
                $sMethod = $aMatch[0][$iCount - 1];
                array_pop($aPathmatch);
                $sModPath = implode('/', $aPathmatch);

                return $this->parsePath($sModPath, $iDepth + 1, $sMethod);
            }

            return false;
        }

        return array(
            'controller' => $sController,
            'method' => $sMethod,
            'path' => implode('/', $aPathmatch)
        );
    }

    /**
     * 매핑 규칙 파라미터에서 역매칭을 이용환 치환작업을 시도한다.
     *
     * @param string $str
     * @param string $regex
     * @param array &$data
     */
    final protected function replaceDeep($str, $regex, &$data)
    {
        if (empty($data)) return;

        foreach ($data as &$d) {
            if (is_array($d)) {
                return $this->replaceDeep($str, $regex, $d);
            }

            $d = preg_replace($regex, $d, $str);
        }
    }

    /**
     * 문자열의 첫번째 슬래쉬 문자를 제거한다.
     *
     * @param string $str
     * @return string
     */
    final protected function stripFirstSlashes($str)
    {
        $str = preg_replace('@^[/]+@', '', $str);

        return $str;
    }
}
